iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 27
0
Mobile Development

Android 十全大補系列 第 27 篇

[Android 十全大補] Espresso

  • 分享至 

  • xImage
  •  

我們講完了一般的 unit test,是時候來測試一些 Android UI 相關的程式了。
基本上 UI test 會做以下這幾件事情:

  1. 找出某些 View
  2. 操作某些 View
  3. 比對某些 View

我們今天會以 Android 官方推薦的 espresso 為教學,馬上就開始吧!

Install

首先一樣是加上 dependency:

dependencies {
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test:rules:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

還記得我們 /src 下有 /main、/test 跟 /androidTest 三個資料夾嗎?
androidTestImplementation 就是針對 /androidTest 的 dependency 設定。

另外在 android.defaultConfig 必須加上以下設定:

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

以下是一個完整的 build.gradle 範例檔案:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28

    defaultConfig {
        applicationId "com.example.androidtestsample"
        minSdkVersion 15
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
}

dependencies {
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test:rules:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

Usage

我們一開始所說的三件事情,在 espresso 中也有相對應的函示:

  1. 找出某些 View:使用 ViewMatcher,
    提供了類似 withId、withText 等找出 View 的方法。
  2. 操作某些 View:使用 ViewInteraction,
    一般先使用 onView 建立 ViewInteraction 然後就可以呼叫 perform 來進行像是 click、typeText 等 View 的操作。
  3. 比對某些 View:使用 ViewAssertion,
    首先用 matches 建立我們的 ViewAssertion,然後在 ViewInteraction 下使用 check 函式來連結我們的 ViewAssertion。

如果大家還是很模糊的話,讓我們來看個例子,假設我們在程式端有以下程式碼:

val account = findViewById<TextView>(R.id.account)
val submit = findViewById<Button>(R.id.submit)
submit.isEnabled = false
account.addTextChangedListener(object : TextWatcher {
    override fun afterTextChanged(s: Editable?) {
    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
    }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        if (s != null) {
            submit.isEnabled = s.isNotEmpty()
        } else {
            submit.isEnabled = false
        }
    }

})

如果我們想要測試當 account 輸入的時候,submit 的狀態有沒有正常跟著改變就可以這樣寫:

@RunWith(AndroidJUnit4::class)
class LoginActivityTest {
    @Rule
    @JvmField
    val activityRule = ActivityTestRule(LoginActivity::class.java)

    @Test
    fun checkSubmitState() {
        // submit should be disable at first
        onView(withId(R.id.submit))
            .check(matches(not(isEnabled())))

        // type Jintin
        onView(withId(R.id.account))
            .perform(typeText("Jintin"))
        // submit should be enable now
        onView(withId(R.id.submit))
            .check(matches(isEnabled()))

        // clear the text
        onView(withId(R.id.account))
            .perform(clearText())
        // submit should be disable now
        onView(withId(R.id.submit))
            .check(matches(not(isEnabled())))
    }

}

跟 unit test 一樣,不論是函示或 class 前面都有個小綠箭頭可以執行我們的測試。

onView 有點像 espresso 的起手式,裡面的 withId 可以幫我們找到我們關注的 View。
接下來藉由 perform 來執行一或多個動作,比如說是 typeText、click 或 clearText。
第三步就是藉由 check 來執行 ViewAssertion 的檢核,matches 會將 ViewMatcher 包裝成 ViewAssertion ,常見的 ViewMatcher 有 isEnabled、isDisplayed 等,狀態基本上都是正面表列,有需要的話也可以跟 not 這種可以轉換成反面的 matcher 連起來使用(就像我們的 matches(not(isEnabled())))。

是不是跟測試 3A 很像呢,以上就是今天的內容了,感謝大家!
也歡迎參考 Android 十全大補的測試三部曲的其他文章:

參考資料:
https://developer.android.com/training/testing/espresso

Android 十全大補已經正式出書上架囉!
有興趣的讀者歡迎參考:
https://www.tenlong.com.tw/products/9789864345786


上一篇
[Android 十全大補] Mockito
下一篇
[Android 十全大補] Jenkins
系列文
Android 十全大補 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言